﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using CrawlerCore;
using HtmlAgilityPack;
using WapCrawlerCore.Classes;
using WapCrawlerLib;


namespace WapCrawlerCore.WapCrawler
{
    public abstract class WapSiteBase// : IWapSite
    {
        //public WapDataClassesDataContext _dc = new WapDataClassesDataContext();

        public BrowserSession_General Browser;
        public WapCrawlerLib.WapCrawler objWapCrawler;
        public bool isAllowUpdate = false; //Check to see if a post exists then update
        protected WapSiteBase(int wapCrawlerId)
        {
            WapDataClassesDataContext dc = new WapDataClassesDataContext();
            //Init browser session
            Browser = new BrowserSession_General();
            //Init the wapsite
            objWapCrawler = dc.WapCrawlers.Single(p => p.wapCrawlerId == wapCrawlerId);
        }

        #region IWapSite Members

        //public void StartCrawlerGauPanda()
        //{
        //    if (objWapCrawler.recentCrawlerUrl != string.Empty)
        //    {
        //        GetPages(objWapCrawler.wapSiteUrl, objWapCrawler.recentCrawlerUrl);
        //    }
        //}

        ///// <summary>
        ///// Tạo post mới nếu chưa có, nếu có rồi thì update
        ///// Tạo topic mới nếu chưa có, nếu có rồi thì update
        ///// Tạo liên kết giữa topic với post
        ///// </summary>
        ///// <param name="postUrl"></param>
        ///// <param name="postTitle"></param>
        ///// <param name="thumbnailUrl"></param>
        ///// <param name="postHead"></param>
        ///// <param name="topicName"></param>
        //public void UpdateDB(string postUrl, string postTitle, string thumbnailUrl, string postHead, string topicName)
        //{
        //    //========================================================
        //    //Lấy thông tin của item từ csdl
        //    PostCrawler objPostCrawler = new PostCrawler();
        //    try
        //    {
        //        //Lấy post theo postUrl nếu tồn tạis
        //        objPostCrawler = objPostCrawler.Get(postUrl);
        //    }
        //    catch
        //    {
        //        //========================================================
        //        //Tạo post mới nếu chưa có
        //        objPostCrawler = objPostCrawler.Insert(postUrl);
        //    }

        //    //============================================================
        //    //Cập nhật lại thông tin
        //    objPostCrawler.postTitle = postTitle;
        //    objPostCrawler.postThumbnailUrl = thumbnailUrl;
        //    objPostCrawler.postHead = postHead;
        //    objPostCrawler.Update(objPostCrawler);

        //    //========================================================
        //    //Lấy topic
        //    TopicCrawler objTopicCrawler = new TopicCrawler();
        //    try
        //    {
        //        objTopicCrawler = objTopicCrawler.Get(topicName, objWapCrawler.wapCrawlerId);
        //    }
        //    catch
        //    {
        //        objTopicCrawler.topicName = topicName;
        //        objTopicCrawler.wapCrawlerId = objWapCrawler.wapCrawlerId;
        //        objTopicCrawler = objTopicCrawler.Insert(objTopicCrawler);
        //    }

        //    //========================================================
        //    //Tạo liên kết Topic với Post nếu chưa có, nếu có rồi thì load
        //    TopicPostCrawler objTopicPostCrawler = new TopicPostCrawler();
        //    try
        //    {
        //        objTopicPostCrawler = objTopicPostCrawler.Get(objTopicCrawler.topicCrawlerId, objPostCrawler.postCrawlerId);
        //    }
        //    catch
        //    {
        //        objTopicPostCrawler.topicCrawlerId = objTopicCrawler.topicCrawlerId;
        //        objTopicPostCrawler.postCrawlerId = objPostCrawler.postCrawlerId;
        //        objTopicPostCrawler.Insert(objTopicPostCrawler);
        //    }
        //}

        /// <summary>
        /// Tạo post mới nếu chưa có, nếu có rồi thì update
        /// Tạo topic mới nếu chưa có, nếu có rồi thì update
        /// Tạo liên kết giữa topic với post
        /// </summary>
        /// <param name="postUrl"></param>
        /// <param name="postTitle"></param>
        /// <param name="thumbnailUrl"></param>
        /// <param name="postHead"></param>
        /// <param name="topicName"></param>
        public void UpdateDB(string postUrl, string postTitle, string thumbnailUrl, string postHead, string topicName)
        {
            
            WapDataClassesDataContext dc = new WapDataClassesDataContext();
            //========================================================
            //Lấy thông tin của item từ csdl
            PostCrawler objPostCrawler = new PostCrawler();
            try
            {
                objPostCrawler = dc.PostCrawlers.Single(p => p.postUrl == postUrl);
                
            }
            catch
            {
                objPostCrawler.postUrl = postUrl;
                dc.PostCrawlers.InsertOnSubmit(objPostCrawler);
                dc.SubmitChanges();
            }

            //============================================================
            //Cập nhật lại thông tin
            objPostCrawler.postTitle = postTitle;
            objPostCrawler.postThumbnailUrl = thumbnailUrl;
            objPostCrawler.postHead = postHead;
            dc.SubmitChanges();

            //========================================================
            //Lấy topic
            TopicCrawler objTopicCrawler = new TopicCrawler();
            try
            {
                objTopicCrawler = dc.TopicCrawlers.Single(p => p.topicName.ToLower() == topicName.ToLower() && p.wapCrawlerId == objWapCrawler.wapCrawlerId);
            }
            catch
            {
                objTopicCrawler.topicName = topicName;
                dc.TopicCrawlers.InsertOnSubmit(objTopicCrawler);
                dc.SubmitChanges();
            }

            //========================================================
            //Tạo liên kết Topic với Post nếu chưa có, nếu có rồi thì load
            TopicPostCrawler objTopicPostCrawler = new TopicPostCrawler();

            //Delete all existing TopicPost
            var query = from p in dc.TopicPostCrawlers
                        where p.postCrawlerId == objPostCrawler.postCrawlerId
                        select p;
            dc.TopicPostCrawlers.DeleteAllOnSubmit(query);
            dc.SubmitChanges();

            //Insert new TopicPost
            objTopicPostCrawler.topicCrawlerId = objTopicCrawler.topicCrawlerId;
            objTopicPostCrawler.postCrawlerId = objPostCrawler.postCrawlerId;
            dc.TopicPostCrawlers.InsertOnSubmit(objTopicPostCrawler);
            dc.SubmitChanges();
        }

        public virtual void StartCrawler(int topicCrawlerId)
        {
           throw new NotImplementedException();
        }

        public void GetPages(string wapUrl, string crawlerUrl, string patternPage, string pagingXPath)
        {
            string pageUrl = GeneralClass.GetFullUrl(wapUrl, string.Format(crawlerUrl, 1));
            int pageIndex = 1;
            //pattern is /game/?trang={0} cat_id=(?<cat_id>\d+)
            Regex r = new Regex(patternPage);
            Match m = r.Match(pageUrl);
            if (m.Success)
                pageIndex = int.Parse(m.Result("${page}"));

            int pageNum, pageMax = 1;
            HtmlDocument doc = Browser.Get(pageUrl);
            HtmlNodeCollection nodeCollection = doc.DocumentNode.SelectNodes(pagingXPath);
            if (nodeCollection != null)
            {
                //Lấy số lượng trang tối đa hiện có
                foreach (HtmlNode nodePage in nodeCollection)
                {
                    try
                    {
                        pageNum = int.Parse(nodePage.InnerHtml);
                        if (pageNum > pageMax)
                            pageMax = pageNum;
                    }
                    catch
                    {

                    }
                }

                //save current page
                WapDataClassesDataContext dc = new WapDataClassesDataContext();
                for (int i = pageIndex; i < pageMax+1; i++ )
                {
                    //infor of a item
                    string nextPageUrl = string.Format(crawlerUrl, i);
                    //if exist post and not allow update
                    if (!GetItemsOfPage(nextPageUrl))
                    {
                        nextPageUrl = string.Format(crawlerUrl, 1);

                        objWapCrawler = dc.WapCrawlers.Single(p => p.wapCrawlerId == objWapCrawler.wapCrawlerId);
                        objWapCrawler.recentCrawlerUrl = nextPageUrl;
                        dc.SubmitChanges();
                        break;
                    }
                    else
                    {
                        objWapCrawler = dc.WapCrawlers.Single(p => p.wapCrawlerId == objWapCrawler.wapCrawlerId);
                        objWapCrawler.recentCrawlerUrl = nextPageUrl;
                        dc.SubmitChanges();
                    }
                }
            }
        }

        public virtual bool GetItemsOfPage(string pageUrl)
        {
            throw new NotImplementedException();
        }

        public virtual void GetItem(string postUrl, string topicName)
        {
            throw new NotImplementedException();
        }

        public virtual void Test(string pageUrl, string postTitle)
        {
            throw new NotImplementedException();
        }
        #endregion

        public string FormatContent(string postContent)
        {
            //format content
            postContent = postContent.Trim();
            Regex r1 = new Regex(@"\s+");
            postContent = r1.Replace(postContent, " ");
            r1 = new Regex(@"(<br>(\s|))+");
            postContent = r1.Replace(postContent, @"<br>");
            return postContent;
        }

        public void FormatAll(int wapCrawlerId)
        {
            WapDataClassesDataContext dc = new WapDataClassesDataContext();

            //select topics of wap
            var queryTopicCrawler = from p in dc.TopicCrawlers
                                    where p.wapCrawlerId == wapCrawlerId
                                    select p.topicCrawlerId;

            //select all post
            IQueryable<PostCrawler> queryPostCrawler = from p in dc.TopicPostCrawlers
                                   where queryTopicCrawler.Contains(p.topicCrawlerId)
                                   select p.PostCrawler;
            ;

            foreach (PostCrawler p in queryPostCrawler)
            {
                if (p.postContent != null)
                {
                    p.postContent = FormatContent(p.postContent);
                    dc.SubmitChanges();
                }
            }
            
        }

        public void UpdateMyPost(int postCrawlerId)
        {
            WapDataClassesDataContext dc = new WapDataClassesDataContext();
            PostCrawler postCrawler = dc.PostCrawlers.Single(p => p.postCrawlerId == postCrawlerId);

            //=====================================================================
            //Update info
            Post objPost = dc.Posts.Single(q => q.postCrawlerId == postCrawlerId);

            objPost.title = postCrawler.postTitle;
            objPost.seoTitle = postCrawler.postSeoTitle;
            objPost.thumbnailUrl = postCrawler.postThumbnailUrl;
            objPost.head = postCrawler.postHead;
            objPost.content = postCrawler.postContent;
            dc.SubmitChanges();

            //=====================================================================
            //Add images
            foreach (ImageCrawler imgCrawler in postCrawler.ImageCrawlers)
            {
                Image objImg = new Image();
                try
                {
                    objImg = objPost.Images.Single(p => p.imageCrawlerId == imgCrawler.imageCrawlerId);
                }
                catch
                {
                    objImg.postId = objPost.postId;
                    objImg.imageCrawlerId = imgCrawler.imageCrawlerId;
                    dc.Images.InsertOnSubmit(objImg);
                    dc.SubmitChanges();
                }

                //update
                objImg.name = imgCrawler.imageName;
                objImg.url = imgCrawler.imageUrl;
                objImg.pattern = imgCrawler.imagePattern;
                objImg.status = imgCrawler.imageStatus;
                dc.SubmitChanges();
            }

            //=====================================================================
            //Add files
            foreach (FileCrawler fileCrawler in postCrawler.FileCrawlers)
            {
                File objFile = new File();
                try
                {
                    objFile = objPost.Files.Single(p => p.fileCrawlerId == fileCrawler.fileCrawlerId);
                }
                catch
                {
                    objFile.postId = objPost.postId;
                    objFile.fileCrawlerId = fileCrawler.fileCrawlerId;
                    dc.Files.InsertOnSubmit(objFile);
                    dc.SubmitChanges();
                }

                //update
                objFile.name = fileCrawler.fileName;
                objFile.url = fileCrawler.fileUrl;
                objFile.pattern = fileCrawler.filePattern;
                objFile.status = fileCrawler.fileStatus;
                dc.SubmitChanges();
            }
            
        }

        /// <summary>
        /// Add postcrawler to post in database
        /// If exist then update
        /// </summary>
        /// <param name="postCrawlerId"></param>
        public void AddMyPost(int postCrawlerId)
        {
            WapDataClassesDataContext dc = new WapDataClassesDataContext();
            PostCrawler postCrawler = dc.PostCrawlers.Single(p => p.postCrawlerId == postCrawlerId);

            Post objPost = new Post();
            try
            {
                //If exist post then update
                objPost = dc.Posts.Single(p => p.postCrawlerId == postCrawlerId);
                UpdateMyPost(postCrawlerId);
            }
            catch
            {
                //Create new
                CreateMyPost(postCrawlerId);
            }
        }

        public void CreateMyPost(int postCrawlerId)
        {
            WapDataClassesDataContext dc = new WapDataClassesDataContext();
            PostCrawler postCrawler = dc.PostCrawlers.Single(p => p.postCrawlerId == postCrawlerId);

            //=====================================================================
            //Add Post
            Post objPost = new Post();
            objPost.postCrawlerId = postCrawler.postCrawlerId;
            objPost.title = postCrawler.postTitle;
            objPost.seoTitle = postCrawler.postSeoTitle;
            objPost.thumbnailUrl = postCrawler.postThumbnailUrl;
            objPost.head = postCrawler.postHead;
            objPost.content = postCrawler.postContent;
            dc.Posts.InsertOnSubmit(objPost);
            dc.SubmitChanges();

            //=====================================================================
            //Add images
            foreach (ImageCrawler imgCrawler in postCrawler.ImageCrawlers)
            {
                Image objImg = new Image();
                objImg.name = imgCrawler.imageName;
                objImg.url = imgCrawler.imageUrl;
                objImg.pattern = imgCrawler.imagePattern;
                objImg.status = imgCrawler.imageStatus;
                objImg.imageCrawlerId = imgCrawler.imageCrawlerId;
                objImg.postId = objPost.postId;
                dc.Images.InsertOnSubmit(objImg);
            }

            //=====================================================================
            //Add files
            foreach (FileCrawler fileCrawler in postCrawler.FileCrawlers)
            {
                File objFile = new File();
                objFile.name = fileCrawler.fileName;
                objFile.url = fileCrawler.fileUrl;
                objFile.pattern = fileCrawler.filePattern;
                objFile.status = fileCrawler.fileStatus;
                objFile.fileCrawlerId = fileCrawler.fileCrawlerId;
                objFile.postId = objPost.postId;
                dc.Files.InsertOnSubmit(objFile);
            }
            dc.SubmitChanges();
        }
    }
}
